package cn.zebra.dev.member.module.security.service;

import cn.zebra.dev.base.module.member.entity.BaseMember;
import cn.zebra.dev.base.module.member.service.BaseMemberService;
import cn.zebra.dev.common.constant.SysConstant;
import cn.zebra.dev.common.utils.StrUtils;
import cn.zebra.dev.member.module.security.entity.MemberDetailsEntity;
import com.alibaba.fastjson.JSON;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.data.redis.core.ValueOperations;
import org.springframework.scheduling.annotation.Async;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.stereotype.Service;

import java.util.concurrent.TimeUnit;

/**
 * 用户详细信息
 *
 * @author runnable@sina.cn
 */

@Slf4j
@Service
public class MemberDetailsServiceImpl implements UserDetailsService {

    @Autowired
    private StringRedisTemplate redisTemplate;

    @Autowired
    private BaseMemberService baseMemberService;

    /**
     * 获取用户信息
     *
     * @param userName 用户名/用户账号/用户手机号
     */
    @Override
    public UserDetails loadUserByUsername(String userName) {
        ValueOperations<String, String> valueOperations = redisTemplate.opsForValue();
        String key = SysConstant.MEMBER + userName;
        String json = valueOperations.get(key);
        if (StrUtils.isNotBlank(json)) {
            MemberDetailsEntity memberDetailsEntity = JSON.parseObject(json, MemberDetailsEntity.class);
            memberDetailsEntity.setLoginName(userName);
            return memberDetailsEntity;
        }
        BaseMember member = baseMemberService.findMemberByPhone(userName);
        if (member == null) {
            member = baseMemberService.findByMemberName(userName);
        }
        if (member == null) {
            log.error(String.format("用户[%s]不存在数据库!", userName));
            throw new NullPointerException();
        }
        MemberDetailsEntity detailsEntity = new MemberDetailsEntity(member);
        detailsEntity.setLoginName(userName);
        saveRedis(key, valueOperations, detailsEntity);
        return detailsEntity;
    }

    /**
     * 异步存放至redis
     *
     * @param key             键
     * @param valueOperations redisOperations
     * @param detailsEntity   用户对象
     */
    @Async
    void saveRedis(String key, ValueOperations<String, String> valueOperations, MemberDetailsEntity detailsEntity) {
        valueOperations.set(key, JSON.toJSONString(detailsEntity), 7, TimeUnit.DAYS);
    }
}
